package com.lsh.streamgd.sparql;

import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.update.UpdateAction;
import com.hp.hpl.jena.update.UpdateFactory;
import com.hp.hpl.jena.update.UpdateRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 14-3-4.
 */
public class SparqlExecution {
    //Service
    public static List<Map<String, String>> jQuery(String service, String query, String... objects) {
        Query sparql = QueryFactory.create(query);
        ARQ.getContext().setTrue(ARQ.useSAX);
        //Executing SPARQL Query and pointing to the DBpedia SPARQL Endpoint
        QueryExecution qexec = QueryExecutionFactory.sparqlService(service, sparql);
        //Retrieving the SPARQL Query results
        ResultSet rs = qexec.execSelect();

        return extract(rs, objects);
    }

    //Construct
    public static Model construct(Model set, String query) {
        Query sparql = QueryFactory.create(query);
        QueryExecution qe = QueryExecutionFactory.create(sparql, set);

        return qe.execConstruct();
    }

    //Update
    public static void update(Model model, String query) {
        model.enterCriticalSection(Lock.WRITE);

        try {
            UpdateRequest req = UpdateFactory.create(query);
            UpdateAction.execute(req, model);
        } finally {
            model.leaveCriticalSection();
        }
    }

    //Query sparql in Virtuoso linked database with Jena API.
    public static List<Map<String, String>> jQuery(Model set, String query, String... objects) {
        set.enterCriticalSection(Lock.READ);

        try {
            Query sparql = QueryFactory.create(query);
            QueryExecution qe = QueryExecutionFactory.create(sparql, set);
            ResultSet rs = qe.execSelect();

            return extract(rs, objects);
        } finally {
            set.leaveCriticalSection();
        }
    }

    //Extract triples' information in ResultSet according to required objects.
    private static List<Map<String, String>> extract(ResultSet resultSet, String... objects) {
        List<Map<String, String>> list = new ArrayList<>();

        while (resultSet.hasNext()) {
            Map<String,String> rm = new HashMap<>();
            QuerySolution row = resultSet.nextSolution();

            if (null != objects) {
                for (int i=0;i<objects.length;i++) {
                    RDFNode node = row.get(objects[i]);
                    rm.put(objects[i], node.toString());
                }
            }

            list.add(rm);
        }

        return list;
    }
}